// 数据仓库
import { useRef, useState } from 'react'
import { unstable_batchedUpdates } from 'react-dom'
// 对外接口
const formInstanceApi = [
	'setCallback',
	'dispatch',
	'registerValidateFields',
	'resetFields',
	'setFields',
	'setFieldsValue',
	'getFieldsValue',
	'getFieldValue',
	'validateFields',
	'submit',
	'unRegisterValidate',
]
const isReg = (value) => value instanceof RegExp
class FormStore {
	constructor(forceUpdate, defultFormValue = {}) {
		this.FormUpdate = forceUpdate /* 更新 form */
		this.model = {} /* 表单状态层 */
		this.control = {} /* 控制每个 formItem 的控制器 */
		this.isSchedule = false /* 开启调度 */
		this.callback = {} /* 存放监听函数 callback */
		this.penddingValidateQueue = [] /* 批量更新队列 */
		this.defultFormValue = defultFormValue /* 表单初始化的值 */
	}
	/* 
        提供操作 from 的方法 
        只暴露出去重要模块 如果所有模块都暴露出去，防止串改模块下的其他内容
    */
	getForm() {
		return formInstanceApi.reduce((map, item) => {
			map[item] = this[item].bind(this)
			return map
		}, {})
	}
	/* 创建一个验证模块 */
	static createValidate(validate) {
		const {
			value = '',
			rule = () => true,
			required = false,
			messsage = '',
		} = validate
		return {
			value,
			rule,
			required,
			messsage,
			status: 'pending',
		}
	}
	/*处理回调函数 */
	setCallback = (callback) => {
		if (callback) {
			this.callback = callback
		}
	}
	/* 触发事件 */
	dispatch(action, ...arg) {
		if (!action || typeof action !== 'object') return null
		const { type } = action
		if (
			~formInstanceApi.indexOf(type) ||
			typeof this[type] === 'function'
		) {
			return this[type](...arg)
		}
	}
	/* 注册表单单元项 */
	registerValidateFields(name, control, model) {
		if (this.defultFormValue[name]) {
			model.value = this.defultFormValue[name]
		}
		const validate = FormStore.createValidate(model)
		this.model[name] = validate
		this.control[name] = control
	}
	/* 卸载注册表单单元项 */
	unRegisterValidate(name) {
		delete this.model[name]
		delete this.control[name]
	}
	/* 通知对应的 formItem 更新 */
	notifyChange(name) {
		const controller = this.control[name]
		controller?.changeValue?.()
	}
	/* 重置表单 */
	resetFields() {
		Object.keys(this.model).forEach((modelName) => {
			this.setValueClearStatus(this.model[modelName], modelName, null)
		})
	}
	// 设置一组字段状态
	setFields(object) {
		if (typeof object !== 'object') return
		Object.keys(object).forEach((modelName) => {
			this.setFieldsValue(modelName, object[modelName])
		})
	}
	/* 设置表单值 */
	setFieldsValue(name, modelValue) {
		const model = this.model[name]
		if (!model) return
		if (typeof modelValue === 'object') {
			/* 设置表单项 */
			const { message, rule, value } = modelValue
			if (message) model.message = message
			if (rule) model.rule = rule
			if (value) model.value = value
			model.status = 'pending'
			this.validateField(name, true) /* 验证规则 */
		} else {
			this.setValueClearStatus(model, name, modelValue)
		}
	}
	/* 复制并清空状态 */
	setValueClearStatus(model, name, value) {
		model.value = value
		model.status = 'pending'
		this.notifyChange(name)
	}
	/* 获取表单数据层的值 */
	getFieldsValue = () => {
		const formData = {}
		Object.keys(this.model).forEach((modelName) => {
			formData[modelName] = this.model[modelName].value
		})
		return formData
	}
	/* 获取表单模型 */
	getFieldmodel(name) {
		const model = this.model[name]
		return model || {}
	}
	/* 获取对应字段名的值 */
	getFieldValue = (name) => {
		const model = this.model[name]
		// 没有注册 但是有默认值
		if (!model && this.defultFormValue[name])
			return this.defultFormValue[name]
		return model?.value || null
	}
	// 表单校验
	validateField(name, forceUpdate = false) {
		const model = this.model[name]
		// 记录上次状态
		const lastStatus = model.status
		if (!model) return null

		const { required, value, rule } = model
		let status = 'resolve'
		if (required && !value) {
			status = 'reject'
		} else if (isReg(rule)) {
			status = rule.test(value) ? 'resolve' : 'reject'
		} else if (typeof rule === 'function') {
			/* 自定义校验规则 */
			status = rule(value) ? 'resolve' : 'reject'
		}
		model.status = status
		if (lastStatus !== status || forceUpdate) {
			// 首先状态的改变带来的视图更新没那么重要 可以执行优先级更高的任务，
			// 还有一点就是整个验证功能，有可能在异步情况下，表单有多个单元
			// 如果直接执行，可能会让表达更新多次
			const notify = this.notifyChange.bind(this, name)
			this.penddingValidateQueue.push(notify)
		}
		this.scheduleValidate()
		return status
	}
	/* 批量调度验证更新任务 */
	scheduleValidate() {
		if (this.isSchedule) return
		this.isSchedule = true
		Promise.resolve().then(() => {
			// 批量更新验证任务
			unstable_batchedUpdates(() => {
				do {
					const notify = this.penddingValidateQueue.shift()
					notify?.() /* 触发更新 */
				} while (this.penddingValidateQueue.length)
				this.isSchedule = false
			})
		})
	}
	// 表单整体验证
	validateFields(callback) {
		let status = true
		Object.keys(this.model).forEach((modelName) => {
			const modalStatus = this.validateField(modelName, true)
			if (modalStatus === 'reject') {
				// console.log('modelName :>>', modelName)
				status = false
			}
		})
		callback?.(status)
	}

	submit(callback) {
		this.validateFields((res) => {
			const { onFinish, onFinishFailed } = this.callback
			callback?.(res)
			if (!res) onFinishFailed?.() /* 验证失败*/
			onFinish?.(this.getFieldsValue()) /* 验证成功 */
		})
	}
}
export default function useForm(form, defultFormValue = {}) {
	const formRef = useRef(null)
	const [, setState] = useState({})
	if (!formRef.current) {
		if (form) {
			formRef.current = form
		} else {
			const formStore = new FormStore(setState, defultFormValue)
			// 获取实例方法
			formRef.current = formStore.getForm()
		}
	}
	return [formRef.current]
}
